package cn.sangedon.review.data.service.impl;

import cn.sangedon.review.common.constant.TypeConstant;
import cn.sangedon.review.common.domain.data.StockDayInfo;
import cn.sangedon.review.common.query.data.StockDayInfoQuery;
import cn.sangedon.review.common.service.data.StockDayInfoService;
import cn.sangedon.review.common.service.data.TradingDateService;
import cn.sangedon.review.data.mapper.StockDayInfoMapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

/**
 * @author dongliangqiong
 * @description 针对表【tb_stock_day_info(k线数据表)】的数据库操作Service实现
 * @createDate 2022-08-25 12:41:41
 */
@Slf4j
@DubboService
public class StockDayInfoServiceImpl extends ServiceImpl<StockDayInfoMapper, StockDayInfo> implements StockDayInfoService {
    @Autowired
    private TradingDateService tradingDateService;

    @Override
    public Map<String, Object> listByCondition(StockDayInfoQuery stockDayInfoQuery) {
        QueryWrapper<StockDayInfo> query = createCountQuery(stockDayInfoQuery);
        long count = this.count(query);
        List<StockDayInfo> list = this.list(afterCountQuery(stockDayInfoQuery, query));

        Map<String, Object> resMap = new HashMap<>();
        resMap.put("data", list);
        resMap.put("count", count);
        return resMap;
    }

    @Override
    public List<StockDayInfo> getStockDayInfos(StockDayInfoQuery stockDayInfoQuery) {
        return this.list(createListQuery(stockDayInfoQuery));
    }

    @Override
    public Long countStockDayInfos(StockDayInfoQuery stockDayInfoQuery) {
        return this.count(createCountQuery(stockDayInfoQuery));
    }

    @Override
    public List<StockDayInfo> getStockDayInfos(String time, Integer type) {
        if (!StringUtils.hasText(time)) {
            log.info("待查询的交易日为空");
            return new ArrayList<>();
        }
        QueryWrapper<StockDayInfo> query = new QueryWrapper<>();
        if (TypeConstant.EQ.equals(type)) {
            query.eq("trading_date", time);
        } else if (TypeConstant.GE.equals(type)) {
            query.ge("trading_date", time);
        } else if (TypeConstant.GT.equals(type)) {
            query.gt("trading_date", time);
        }
        return this.list(query);
    }

    @Override
    public String getLatestDate() {
        return this.baseMapper.getLatestDate();
    }

    @Override
    public List<StockDayInfo> search(String keyword, Integer num) {
        QueryWrapper<StockDayInfo> query = new QueryWrapper<>();
        query.like("name", keyword);
        query.or();
        query.eq("code", keyword);
        query.orderByDesc("trading_date");
        query.last(" limit " + num);
        return this.list(query);
    }

    @Override
    public void fillData(String tradeDate) {
        List<StockDayInfo> stockDayInfos = this.getStockDayInfos(tradeDate, TypeConstant.EQ);
        String preTradeDate = tradingDateService.getTradeDateAgo(tradeDate, 1);
        List<StockDayInfo> preStockDayInfos = this.getStockDayInfos(preTradeDate, TypeConstant.EQ);
        Map<String, StockDayInfo> dayInfoMap = preStockDayInfos.stream()
                                                               .collect(Collectors.toMap(StockDayInfo::getCode, Function.identity()));

        stockDayInfos.forEach(e -> {
            StockDayInfo stockDayInfo = dayInfoMap.get(e.getCode());
            if (stockDayInfo == null) {
                return;
            }
            e.setLastClosePrice(stockDayInfo.getClosingPrice());
            this.updateById(e);
        });
    }

    private Wrapper<StockDayInfo> createListQuery(StockDayInfoQuery stockDayInfoQuery) {
        return afterCountQuery(stockDayInfoQuery, createCountQuery(stockDayInfoQuery));
    }

    private Wrapper<StockDayInfo> afterCountQuery(StockDayInfoQuery stockDayInfoQuery, QueryWrapper<StockDayInfo> query) {
        query.orderByDesc("trading_date");
        query.orderByDesc("change_rate");
        if (stockDayInfoQuery.getPageNo() != null && stockDayInfoQuery.getPageSize() != null) {
            query.last(
                " limit " + (stockDayInfoQuery.getPageNo() - 1) * stockDayInfoQuery.getPageSize() + ", " + stockDayInfoQuery.getPageSize());
        }
        return query;
    }

    private QueryWrapper<StockDayInfo> createCountQuery(StockDayInfoQuery stockDayInfoQuery) {
        if (!StringUtils.hasText(stockDayInfoQuery.getEndTime()) && !StringUtils.hasText(stockDayInfoQuery.getEndTime()) &&
            stockDayInfoQuery.getPageNo() == null && stockDayInfoQuery.getPageSize() == null) {
            String latestDate = this.getLatestDate();
            query().eq("trading_date", latestDate);
        }

        QueryWrapper<StockDayInfo> query = new QueryWrapper<>();
        if (StringUtils.hasText(stockDayInfoQuery.getStartTime())) {
            query.ge("trading_date", stockDayInfoQuery.getStartTime());
        }

        if (StringUtils.hasText(stockDayInfoQuery.getEndTime())) {
            query.le("trading_date", stockDayInfoQuery.getEndTime());
        }
        return query;
    }
}




